import json
import re

from django.contrib.auth import login, authenticate, logout
from django.core.paginator import Paginator
from django.shortcuts import render, redirect
from django.urls import reverse
from django.views import View
from django import http
from django_redis import get_redis_connection

from apps.index.utils import get_user_info
from apps.news.models import UserCollection, Category, News, UserFans
from apps.users.models import User
from utils import constants
from utils.image_storage import storage
from utils.response_code import RET


class RegisterView(View):
    def post(self, request):
        # 1. 获取参数
        json_dict = json.loads(request.body.decode())
        mobile = json_dict.get("mobile")
        smscode = json_dict.get("smscode")
        password = json_dict.get("password")
        print(json_dict)
        # 2. 校验参数
        if not all([mobile, smscode, password]):
            return http.JsonResponse({'errno': RET.PARAMERR, 'errmsg': "参数"})

        # 校验手机号是否正确
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.JsonResponse({'errno': RET.PARAMERR, 'errmsg': "手机号格式不正确"})

        # 3. 从redis的真实的短信验证码内容
        try:
            redis_conn = get_redis_connection('code')
            real_sms_code = redis_conn.get("SMS_" + mobile)
        except Exception as e:
            return http.JsonResponse({'errno': RET.DBERR, 'errmsg': "数据查询失败"})

        if not real_sms_code:
            return http.JsonResponse({'errno': RET.NODATA, 'errmsg': "验证码已过期"})
        # 4. 校验用户输入的短信验证码内容和真实验证码内容是否一致
        real_sms_code = real_sms_code.decode()
        if real_sms_code != smscode:
            return http.JsonResponse({'errno': RET.DATAERR, 'errmsg': "验证码输入错误"})
        # 5.1 添加到数据库
        try:
            user = User.objects.create_user(mobile=mobile, username=mobile, password=password)
        except Exception as e:
            print(333)
            return http.JsonResponse({'errno': RET.DBERR, 'errmsg': "数据保存失败"})

        #  6. 保存用户登录状态
        login(request, user)

        # 7. 返回响应
        response = http.JsonResponse({'errno': RET.OK, 'errmsg': '注册成功'})
        response.set_cookie('username', user.username, max_age=3600 * 24 * 15)
        return response


class LoginView(View):
    def post(self, request):
        # 1. 获取参数
        json_dict = json.loads(request.body.decode())
        mobile = json_dict.get("mobile")
        password = json_dict.get("password")

        # 2. 校验参数
        if not all([mobile, password]):
            return http.JsonResponse({'errno': RET.PARAMERR, 'errmsg': '参数错误'})

        # 校验手机号是否正确
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.JsonResponse({'errno': RET.PARAMERR, 'errmsg': '手机号格式不正确'})
        try:
            user = User.objects.get(mobile=mobile)
        except Exception as e:
            return http.JsonResponse({'errno': RET.NODATA, 'errmsg': '用户找不到'})
        if not user.check_password(password):
            return http.JsonResponse({'errno': RET.NODATA, 'errmsg': '密码错误'})
        login(request, user)
        # 5. 响应
        response = http.JsonResponse({'errno': RET.OK, 'errmsg': '登录成功'})
        response.set_cookie('username', user.username, max_age=3600 * 24 * 15)
        return response


class LogoutView(View):
    def get(self, request):
        # 清理session
        logout(request)

        # 退出登录，重定向到登录页
        response = redirect(reverse('index:index'))

        # 退出登录时清除cookie中的username
        response.delete_cookie('username')

        return response


class GetUserInfoView(View):
    def get(self, request):
        user_info = get_user_info(request)
        context = {
            'data': {
                'user_info': user_info,
            }
        }
        return render(request, 'base_user.html', context=context)


class BaseInfoView(View):
    def get(self, request):
        # 1. 获取当前登录用户的信息
        user_info = get_user_info(request)
        context = {
            'data': {
                'user_info': user_info,
            }
        }
        return render(request, 'user_base_info.html', context=context)

    def post(self, request):
        # 2. 获取到传入参数
        data_dict = json.loads(request.body.decode())
        username = data_dict.get("username")
        gender = data_dict.get("gender")
        signature = data_dict.get("signature")
        print(data_dict)
        if not all([username, gender]):
            return http.HttpResponseBadRequest(errno=RET.PARAMERR, errmsg="参数有误")

        if gender not in (['MAN', 'WOMAN']):
            return http.HttpResponseBadRequest(errno=RET.PARAMERR, errmsg="参数有误")

        # 3. 更新并保存数据
        gender_enum = {'MAN': 0, 'WOMAN': 1}
        try:
            request.user.username = username
            request.user.gender = gender_enum[gender]
            if signature:
                request.user.signature = signature
            request.user.save()
        except Exception as e:
            print(e)
            return http.JsonResponse({'errno': RET.DBERR, 'errmsg': "保存数据失败"})
        # 4. 返回响应
        return http.JsonResponse({'errno': RET.OK, 'errmsg': "更新成功"})


class PicInfoView(View):
    def get(self, request):
        user_info = get_user_info(request)
        context = {
            'data': {
                'user_info': user_info,
            }
        }
        return render(request, 'user_pic_info.html', context=context)

    def post(self, request):
        # 1. 获取到上传的文件
        try:
            avatar_file = request.FILES.get("avatar").read()
        except Exception as e:
            return http.JsonResponse({'errno': RET.PARAMERR, 'errmsg': "读取文件出错"})

        # 2. 再将文件上传到七牛云
        try:
            url = storage(avatar_file)
        except Exception as e:
            return http.JsonResponse({'errno': RET.THIRDERR, 'errmsg': "上传图片错误"})

        # 3. 将头像信息更新到当前用户的模型中
        # 将数据保存到数据库
        try:
            # 设置用户模型相关数据
            request.user.avatar_url = url
            request.user.save()
        except Exception as e:
            return http.JsonResponse({'errno': RET.DBERR, 'errmsg': "保存用户数据错误"})

        # 4. 返回上传的结果<avatar_url>
        return http.JsonResponse(
            {'errno': RET.OK, 'errmsg': "OK", 'data': {"avatar_url": constants.QINIU_DOMIN_PREFIX + url}})


class UserFollowView(View):
    def get(self, request):
        # 获取页数
        p = request.GET.get("p", 1)
        try:
            p = int(p)
        except Exception as e:
            print(e)
            p = 1
        try:
            fans = UserFans.objects.filter(fans=request.user)

            # 分页获取
            pagination = Paginator(fans, constants.USER_FOLLOWED_MAX_COUNT)
            # 获取当前页数据
            follows = pagination.page(p)
            # 获取当前页
            current_page = p
            # 获取总页数
            total_page = pagination.num_pages
        except Exception as e:
            return http.JsonResponse({'errno': RET.DBERR, 'errmsg': '我的关注分页失败'})

        user_dict_li = []  # 存放最后的字典数据
        for follow_user in follows:
            user_dict_li.append({
                "id": follow_user.follow.id,
                "username": follow_user.follow.username,
                "avatar_url": follow_user.follow.avatar_url if follow_user.follow.avatar_url else "",
                "mobile": follow_user.follow.mobile,
                "gender": 'WOMAN' if follow_user.follow.gender == 1 else "MAN",
                "signature": follow_user.follow.signature if follow_user.follow.signature else "",
                "followers_count": follow_user.follow.followers.count(),
                "news_count": follow_user.follow.news_list.count()
            })
        context = {'data': {"users": user_dict_li, "total_page": total_page, "current_page": current_page}}

        return render(request, 'user_follow.html', context=context)


class UserPassView(View):
    def get(self, request):
        return render(request, 'user_pass_info.html')

    def post(self, request):
        # 1. 获取到传入参数
        data_dict = json.loads(request.body.decode())
        old_password = data_dict.get("old_password")
        new_password = data_dict.get("new_password")

        if not all([old_password, new_password]):
            return http.JsonResponse({'errno': RET.PARAMERR, 'errmsg': "参数有误"})

        # 2. 获取当前登录用户的信息

        if not request.user.check_password(old_password):
            return http.JsonResponse({'errno': RET.PWDERR, 'errmsg': "原密码错误"})

        try:
            # 更新数据
            request.user.set_password(new_password)
            request.user.save()
        except Exception as e:
            return http.JsonResponse({'errno': RET.DBERR, 'errmsg': "修改密码失败"})
        response = http.JsonResponse({'errno': RET.OK, 'errmsg': "修改密码成功"})
        return response


class UserCollectionView(View):
    def get(self, request):
        # 1获取参数
        # 当前页数
        p = request.GET.get('p', 1)
        try:
            p = int(p)
        except Exception as e:
            print(e)
            p = 1
        # 获取数据
        collections = []  # 存放新闻对象的列表
        current_page = 1  # 当前页
        total_page = 1  # 总页数
        try:
            collects = UserCollection.objects.filter(user=request.user.id)
            pagination = Paginator(collects, constants.USER_COLLECTION_MAX_NEWS)
            current_page = pagination.page
            collections = pagination.page(p)
            total_page = pagination.num_pages
        except Exception as e:
            return http.JsonResponse({'errno': RET.DBERR, 'errmsg': '分页失败'})

        collection_dict_li = []
        # 转为字段数据存到列表里
        for collect in collections:
            collection_dict_li.append({
                "id": collect.news.id,
                "title": collect.news.title,
                "source": collect.news.source,
                "digest": collect.news.digest,
                "create_time": collect.news.create_time,
                "index_image_url": collect.news.index_image_url,
                "clicks": collect.news.clicks,
            })

        print('total_page', total_page)
        print('current_page', current_page)
        # 所有数据
        context = {'data': {"total_page": total_page, "current_page": current_page, "collections": collection_dict_li}}

        return render(request, 'user_collection.html', context=context)


class UserNewsReleaseView(View):
    def get(self, request):
        categories = []
        try:
            # 获取所有的分类数据
            categories = Category.objects.all()
        except Exception as e:
            return http.JsonResponse({'errno': RET.DBERR, 'errmsg': '查询分类失败'})

        # 定义列表保存分类数据
        categories_dicts = []

        for category in categories:
            # 获取字典
            cate_dict = {
                "id": category.id,
                "name": category.name
            }
            # 拼接内容
            categories_dicts.append(cate_dict)

        # 移除`最新`分类
        categories_dicts.pop(0)
        # 返回内容
        context = {'data': {"categories": categories_dicts}}

        return render(request, 'user_news_release.html', context=context)

    def post(self, request):
        # 1获取数据
        title = request.POST.get('title')
        category_id = request.POST.get('category_id')
        digest = request.POST.get('digest')
        content = request.POST.get('content')
        # 图片 index_image 是个文件 对象
        index_image = request.FILES.get('index_image')
        # 来源
        source = '个人发布'

        # 校验
        if not all([title, category_id, digest, index_image, content, source]):
            return http.JsonResponse({'errno': RET.PARAMERR, 'errmsg': '参数有误'})
        # 读取图片
        try:
            index_image = index_image.read()
        except Exception as e:
            return http.JsonResponse({'errno': RET.PARAMERR, 'errmsg': '图片读取有误'})

        # 上传图片
        try:
            key = storage(index_image)
        except Exception as e:
            return http.JsonResponse({'errno': RET.THIRDERR, 'errmsg': '上传图片有误'})
        print('key', key)
        # 保存一条新的新闻
        try:
            News.objects.create(title=title, digest=digest, source=source, content=content,
                                index_image_url=constants.QINIU_DOMIN_PREFIX + key, category_id=category_id,
                                user_id=request.user.id, status=1)
        except Exception as e:
            return http.JsonResponse({'errno': RET.DBERR, 'errmsg': '数据保存失败'})
        # 5. 返回结果
        return http.JsonResponse({'errno': RET.OK, 'errmsg': '发布成功，等待审核'})


class UserNewsListView(View):
    def get(self, request):
        # 获取页数
        p = request.GET.get("p", 1)
        try:
            p = int(p)
        except Exception as e:
            print(e)
            p = 1
        news_li = []
        try:
            news = News.objects.filter(user_id=request.user.id)
            # 查询分页数据 得到pagination对象
            pagination = Paginator(news, constants.USER_COLLECTION_MAX_NEWS)
            # 获取当前页数据
            news_li = pagination.page(p)
            # 获取当前页
            current_page = p
            # 获取总页数
            total_page = pagination.num_pages
        except Exception as e:
            return http.JsonResponse({'errno': RET.DBERR, 'errmsg': '分页失败'})

        news_dict_li = []

        for news_item in news_li:
            news_dict_li.append({
                "id": news_item.id,
                "title": news_item.title,
                "create_time": news_item.create_time.strftime("%Y-%m-%d %H:%M:%S"),
                "status": news_item.status,
                "reason": news_item.reason if news_item.reason else ""
            })
        context = {'data': {"news_list": news_dict_li, "total_page": total_page, "current_page": current_page}}

        return render(request, 'user_news_list.html', context=context)
